# -*- coding: UTF-8 -*-

import os, sys, time
import threading
import uuid
import qrcode
import fitz
import pywebio
from pywebio import start_server
from pywebio.session import info as session_info, download
from pywebio.input import input, textarea, select, checkbox, radio, slider, actions, file_upload, input_group, FLOAT, NUMBER, TEXT
from pywebio.output import put_text, put_markdown, put_buttons, put_scope, get_scope, put_info, put_warning, put_error, put_success, put_html, put_link, put_processbar, put_loading, put_code, put_table, put_button, put_buttons, put_image, put_file, put_tabs, put_collapse, put_scrollable, put_widget, put_row, put_column, put_grid
from settings import FILEPATH, FLASKHTML, FILE2ID, ID2FILE, PASSWD, LINKHEAD

import logging

logging.basicConfig(level=20, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='./testlog', filemode='w')

pywebio.config(title='二维码查看与生成')


class PYWEB:
    _instance_lock = threading.Lock()

    id2file = {}
    file2id = {}

    changed = False

    # 单例模式
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with cls._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = object.__new__(cls)  
        return cls._instance

    def __init__(self):
        with open(FILE2ID, "w+") as f:
            lines = f.readlines()
            files = [x.split("\t")[0] for x in lines]
            ids = [x.strip().split("\t")[1] for x in lines]
            self.file2id = dict(zip(files, ids))
        
        with open(ID2FILE, "w+") as f:
            lines = f.readlines()
            ids = [x.split("\t")[0] for x in lines]
            files = [x.strip().split("\t")[1] for x in lines]
            self.id2file = dict(zip(ids, files))
    
    def generate_html(file="", filepath="", id=""):
        file = str(file).strip()
        if file == "":
            return False
        
        html_content = "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><title>%s</title></head><body style=\"display: flex;justify-content: center;flex-direction: column;background: #0e0e0e;align-items: center;\">"%(str(file))
        
        doc = fitz.open(filepath)
        for page in doc:
            html_content += page.getText('html')

        html_content += "</body></html>"

        with open(FILEPATH+id+"/"+id+".html", 'w', encoding='utf8', newline="") as fw:
            fw.write(html_content)
        
        with open(FLASKHTML+id+".html", 'w', encoding='utf8', newline="") as fw:
            fw.write(html_content)
        
        #logging.info("GENERATE_HTML:"+html_content)

        return True

    def generate_qrcode(file="", filepath="", id=""):
        logging.info("GENERATE_QR:"+str(id))
        if str(id).strip() != "":
            filepath = LINKHEAD + str(id)
            logging.info("GENERATE_QR:"+filepath)
            img = qrcode.make(data=filepath+".html")
            with open(FILEPATH+str(id)+"/"+str(id)+'.png', 'wb') as f:
                img.save(f)
            with open("./image/"+str(id)+".png", "wb") as f:
                img.save(f)
            return True
        else:
            return False

    def add_file(fileinfo=""):
        if fileinfo["filename"].split(".")[-1] != "pdf":
            return False
        file = fileinfo["filename"][0:-4]
        logging.info("FILE_CHECK:"+str(file))
        id = ""
        if file != "" and file in PYWEB.file2id:
            id = PYWEB.file2id[file]
        else:
            if file == "":
                return False
            id = uuid.uuid4()

        try:
            logging.info("TRY_GENERATE0:"+str(file)+"|"+str(id))
            logging.info(FILEPATH+str(id))
            if not os.path.exists(FILEPATH+str(id)):
                os.mkdir(FILEPATH+str(id))
                
            logging.info("TRY_GENERATE:"+str(file)+"|"+str(id))

            content = fileinfo["content"]            
            
            open('./files/'+fileinfo['filename'], 'wb').write(content) 

            filepath = './files/'+fileinfo['filename']

            res1 = PYWEB.generate_html(file, filepath, str(id))
            res2 = PYWEB.generate_qrcode(file, filepath, str(id))
            if not res1 or not res2:
                return False
        except:
            return False

        PYWEB.file2id[str(file)] = str(id)
        PYWEB.id2file[str(id)] = str(file)
        with open(FILE2ID, "w+") as fw:
            fw.write(str(file) + "\t" + str(id) + "\n")
        with open(ID2FILE, "w+") as fw:
            fw.write(str(id) + "\t" + str(file) + "\n")

        return True


    def input_info():
        #put_markdown("`二维码查看与生成系统`")

        info = input_group('二维码查看与生成V-0.1', [
            actions(label='二维码查询', name='check', buttons=[{'label':'全部二维码查询', 'value':'k1'}]),
            input("按文件名称查询", name="filename", type=TEXT, default="", help_text="请输入文件名称"),
            file_upload(label='二维码生成', name='file', help_text="上传pdf文件生成二维码", accept="application/pdf", multiple=False),
            input("请输入操作密码", name="passwd", type=TEXT, default="", required=True, help_text=""),
        ])

        logging.warning("USER_INFO:" + str(type(session_info)) + ":" + str(session_info.user_language) + ";" + str(session_info.user_ip)+";"+str(session_info.user_agent))
        logging.warning("USER_ACTION:" + str(info))
        #logging.info("INPUT_DATA:"+str(info["file"]["filename"]))
        if info["passwd"] != PASSWD:
            put_warning("密码错误, 请重试!")
            return False

        if info["check"] == "k1":
            return {"check" : "k1"}
        elif info["filename"] != "":
            return {"check" : info["filename"]}
        elif info["file"]:
            return {"check" : info["file"]["filename"], "generate" : info["file"]}
        else:
            return False
    
    def data_process(data=""):
        if type(data) == type(False):
            return False
        
        if "generate" in data and data["generate"]:
            PYWEB.add_file(data["generate"])

        logging.info("FILE_CHECK:"+str(PYWEB.file2id))
        result = []
        if "check" in data and data["check"] == "k1":
            for file, id in PYWEB.file2id.items():
                if str(id) + ".html" in os.listdir(FILEPATH+str(id)) and \
                        str(id) + ".png" in os.listdir(FILEPATH+str(id)):
                    result.append([file, str(id) + ".html", str(id) + ".png"])
        elif "check" in data and data["check"].strip() != "":
            for file, id in PYWEB.file2id.items():
                logging.info("FILE2ID_CHECK:"+str(file)+"|"+str(id)+"|"+str(data["check"]))
                if ".pdf" in data["check"]:
                    data["check"] = data["check"][0:-4]
                if data["check"] in file:
                    logging.info("FILE2ID_CHECK2:"+str(file)+"|"+str(id))
                    if str(id) + ".html" in os.listdir(FILEPATH+str(id)) and \
                            str(id) + ".png" in os.listdir(FILEPATH+str(id)):
                        result.append([file, str(id) + ".html", str(id) + ".png"])
        else:
            return False
            
        return result
    
    def output_info(data=""):

        logging.info("OUTPUT_DATA:"+str(data))

        if type(data) == type(False):
            put_info('输入错误，请重试!')
            return False
        
        result = [['文件名称', '二维码', '二维码下载']]

        for x in data:
            id = x[1].strip(".html")
            img_content = open("./image/"+x[2], "rb").read()
            item = [put_link(x[0], "./files/"+x[1], new_window=True), put_image(img_content, width='200px'), put_file(x[0]+".png", img_content, "二维码下载")]
            result.append(item)
        if len(result) > 1:
            put_table(result)
        else:
            put_info('暂无信息')
            return False

        return True

    def task_func():

        input_data = PYWEB.input_info()

        output_data = PYWEB.data_process(data = input_data)

        result = PYWEB.output_info(data = output_data)
    
        return result

if __name__ == "__main__":

    pyweb = PYWEB()

    start_server(PYWEB.task_func, debug=True, port=8783)
